package com.cheche.dn.infrastructure;

import com.cheche.dn.Application;
import com.cheche.dn.common.filter.JsonpFilter;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.stereotype.Controller;
import org.springframework.validation.Validator;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.filter.HiddenHttpMethodFilter;
import org.springframework.web.filter.HttpPutFormContentFilter;
import org.springframework.web.servlet.config.annotation.*;

import java.util.List;

import static org.springframework.context.annotation.ComponentScan.Filter;

@Configuration
@EnableWebMvc
@ComponentScan(basePackageClasses = Application.class, includeFilters = @Filter({Controller.class, RestController.class}), useDefaultFilters = false)
class WebMvcConfig extends WebMvcConfigurerAdapter {
    private static final String RESOURCES_HANDLER = "/static/";
    private static final String RESOURCES_LOCATION = RESOURCES_HANDLER + "**";

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler(RESOURCES_HANDLER).addResourceLocations(RESOURCES_LOCATION);
    }

    @Autowired
    private MessageSource messageSource;

    @Override
    public Validator getValidator() {
        return localValidatorFactoryBean();
    }

    @Bean(name = "validator")
    public LocalValidatorFactoryBean localValidatorFactoryBean() {
        LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
        validator.setValidationMessageSource(messageSource);
        return validator;
    }

    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }

    @Bean
    public MappingJackson2HttpMessageConverter jacksonMessageConverter() {
        MappingJackson2HttpMessageConverter hmc = new MappingJackson2HttpMessageConverter();
        ObjectMapper mapper = new ObjectMapper()
                .configure(SerializationFeature.WRITE_NULL_MAP_VALUES, false)       //忽略map中的null属性
                .setSerializationInclusion(JsonInclude.Include.NON_NULL);           //忽略bean中的null属性
        hmc.setObjectMapper(mapper);
        return hmc;
    }

	@Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
		super.configureMessageConverters(converters);
		converters.add(jacksonMessageConverter());
	}

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        super.addInterceptors(registry);
    }

    // 用于处理编码问题
    @Bean
    public javax.servlet.Filter characterEncodingFilter() {
        CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
        characterEncodingFilter.setEncoding("UTF-8");
        characterEncodingFilter.setForceEncoding(true);
        return characterEncodingFilter;
    }

    // 用于Jsonp处理
    @Bean
    public javax.servlet.Filter jsonpFilter() {
        return new JsonpFilter();
    }

    // 用于处理PUT/PATCH请求参数获取
    @Bean
    public javax.servlet.Filter httpPutFormContentFilter() {
        return new HttpPutFormContentFilter();
    }

    /**
     * 用于处理其他客户端不支持的请求方式传参.
     * 客户端采用POST请求,添加参数如:'_method=delete',服务器会将其转化为标准DELETE请求处理
     * @return Filter
     */
    @Bean
    public javax.servlet.Filter hiddenHttpMethodFilter() {
        return new HiddenHttpMethodFilter();
    }

}
